import {
	Application,
	isHttpError,
	Status,
} from "https://deno.land/x/oak/mod.ts";
import GraphQLService from "./graphql/index.js";
import router from "./router.js";

const app = new Application();

// Logger
app.use(async (ctx, next) => {
	await next();
	const rt = ctx.response.headers.get("X-Response-Time");
	console.log(`${ctx.request.method} ${ctx.request.url} - ${rt}`);
});

// Timing
app.use(async (ctx, next) => {
	const start = Date.now();
	await next();
	const ms = Date.now() - start;
	ctx.response.headers.set("X-Response-Time", `${ms}ms`);
});

// Hello World!
// app.use((ctx) => {
// 	ctx.response.body = "Hello World!11";
// });
app.use(GraphQLService.routes(), GraphQLService.allowedMethods());
app.use(router.routes());
app.use(router.allowedMethods());

// 错误处理
app.use(async (ctx, next) => {
	try {
		await next();
	} catch (err) {
		if (isHttpError(err)) {
			switch (err.status) {
				case Status.NotFound:
					// 处理页面404
					break;
				default:
				// 处理其他状态
			}
		} else {
			// 如果你不能处理这个错误，就重新抛出
			throw err;
		}
	}
});

app.addEventListener("error", (evt) => {
	// Will log the thrown error to the console.
	console.log(evt.error);
});

app.use((ctx) => {
	// Will throw a 500 on every request.
	ctx.throw(500);
});

// 打开服务器
// 应用方法.listen()用于打开服务器，开始监听请求，并处理每个请求的注册中间件。当服务器关闭时，这个方法会返回一个承诺。
// 一旦服务器打开，在开始处理请求之前，应用程序将发射一个 "监听 "事件，可以通过.addEventListener()方法进行监听。例如：.addEventListener()方法。
app.addEventListener("listen", ({ hostname, port, secure }) => {
	console.log(
		`Listening on: ${secure ? "https://" : "http://"}${
			hostname ?? "localhost"
		}:${port}`
	);
});

// 你可以在这里注册中间件

export default app;
